import java.util.*;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.groupingBy;

/**
 * @author hht
 * @ClassName StreamApiTester
 * @Description TODO
 * @Date 2019/2/19 14:20
 * @VERSION 1.0
 */
public class StreamApiTester {

    public static void main(String[] args) {
//        testStreamSpeed();
//        testMap();

//        testMapAndFlatMap();
//        int [] nums = {1,2,3,5,3,2,5};
//        charCount(nums);
//        new StreamApiTester().singleNumber(nums);
        listMapOrderList();
    }

    public static void listMapOrderList(){
        List<Map> result = new ArrayList();
        Map m = new HashMap();
        m.put("keyword","a");
        m.put("cc",5);
        result.add(m);
        m = new HashMap();
        m.put("keyword","a");
        m.put("cc",3);
        result.add(m);
        m = new HashMap();
        m.put("keyword","b");
        m.put("cc",2);
        result.add(m);
        m = new HashMap();
        m.put("keyword","c");
        m.put("cc",6);
        result.add(m);

        Map<String,Integer> r =  result.parallelStream().collect(Collectors.toMap(x -> {
            return  x.get("keyword").toString();
        }, x -> {
            return (Integer) (x.get("cc"));
        }, Integer::sum));
        List<Map.Entry<String,Integer>> list = new ArrayList(r.entrySet());
        list = list.parallelStream().sorted(new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return (o2.getValue()).compareTo(o1.getValue());
            }
        }).collect(Collectors.toList());
        System.out.println(list);
    }

    public static void orderArray(int[] nums){
        nums = Arrays.stream(nums).sorted().toArray();
    }

    /**
     * 计算 每个元素出现的次数
     * @param nums
     */
    public static void charCount(int[] nums){
        long start = System.currentTimeMillis();

        Map<Integer,Integer> result = Arrays.stream(nums).parallel().boxed().collect(Collectors.toMap(w->w,w->1,Integer::sum));
        for(Map.Entry e :result.entrySet()){
            System.out.println(e.getKey()+":"+e.getValue());
        }
        int res = result.entrySet().parallelStream().filter(w->w.getValue()==1).collect(Collectors.toList()).get(0).getKey();
        System.out.println((System.currentTimeMillis()-start));
        start = System.currentTimeMillis();
        Map<Integer,List<Integer>> result2 = Arrays.stream(nums).boxed().collect(groupingBy(Integer::intValue));
//        Map<Integer,Integer> result = Arrays.stream(nums).boxed().map(w,w)

//        int res = result2.entrySet().parallelStream().filter(w->w.getValue().size()==1).collect(Collectors.toList()).get(0).getKey();
        for(Map.Entry e :result.entrySet()){
            System.out.println(e.getKey()+":"+e.getValue());
        }
        System.out.println((System.currentTimeMillis()-start));
        System.out.println(res);
    }

    public int singleNumber(int[] nums) {
        Map<Integer,List<Integer>> result2 = Arrays.stream(nums).boxed().collect(groupingBy(Integer::intValue));
        int res = result2.entrySet().parallelStream().filter(w->w.getValue().size()==1).collect(Collectors.toList()).get(0).getKey();
        return res;
    }

   public static void testRandom(){
        Random seed = new Random();
        Supplier<Integer> random = seed::nextInt;
        Stream.generate(random).limit(10).forEach(System.out::println);
        //Another way
        IntStream.generate(() -> (int) (System.nanoTime() % 100)). limit(10).forEach(System.out::println);
    }

    public static void testMap(){
        List<String> collected = Stream.of("a", "b").collect(Collectors.toList());
        //map和 flatmap比较
        List<Integer> figure = collected.stream().map(s -> {
            Integer i;
            switch (s) {
                case "a":
                    i = 1;
                    break;
                case "b":
                    i = 2;
                    break;
                default:
                    i = -1;
                    break;
            }
            return i;
        }).collect(Collectors.toList());
        figure.stream().forEach(System.out::println);
    }

    public static void testMapAndFlatMap() {
        List<String> words = new ArrayList<String>();
        words.add("hello");
        words.add("word");

        //将words数组中的元素再按照字符拆分，然后字符去重，最终达到["h", "e", "l", "o", "w", "r", "d"]
        //如果使用map，是达不到直接转化成List<String>的结果
        List<String> stringList = words.stream()
                .flatMap(word -> Arrays.stream(word.split("")))
                .distinct()
                .collect(Collectors.toList());
//        stringList.stream().forEach(System.out::println);


        Stream<Stream<Character>> result =  words.stream().map(w -> characterStream(w));
        Stream<Character> letters =  words.stream().flatMap(w -> characterStream(w));

        //不能处理多个sream 只能处理一个，否则不能合并而是返回strem集合
        result.forEach(u -> {
            u.forEach(System.out::println);
        });
        //直接把多个steam合并了
        letters.forEach(System.out::println);


    }
    public static Stream<Character> characterStream(String s){
        List<Character> result = new ArrayList<>();
        for (char c : s.toCharArray())
            result.add(c);
        return result.stream();
    }

    public static void  testStreamSpeed(){
        List<Integer> lists=buildIntRange();
        long start = System.currentTimeMillis();
        for (Integer s:lists){
            try {
                TimeUnit.MILLISECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("非lambda耗时："+(System.currentTimeMillis()-start));
        start = System.currentTimeMillis();
        lists.forEach(i-> {
            try {
                TimeUnit.MILLISECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        System.out.println("lambda耗时："+(System.currentTimeMillis()-start));
        start = System.currentTimeMillis();
        lists.stream().forEach(i-> {
            try {
                TimeUnit.MILLISECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        System.out.println("stream-lambda耗时："+(System.currentTimeMillis()-start));
        start = System.currentTimeMillis();
        lists.parallelStream().forEach(i-> {
            try {
                TimeUnit.MILLISECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        System.out.println("parallelStream-lambda耗时："+(System.currentTimeMillis()-start));
    }

    public static List<Integer> buildIntRange() {
        List<Integer> numbers = new ArrayList<>(5);
        for (int i = 0; i < 5; i++)
            numbers.add(i);
        return Collections.unmodifiableList(numbers);
    }


}
